package gui.Main;

import communications.*;
import hypeerweb.HyPeerWeb;
import hypeerweb.HyPeerWebProxy;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;

/**
 * The central GUI used to display information about the HyPeerWeb and debug information
 * 
 * @author Matthew Smith
 *
 */
public class GUI extends JFrame
{
	private static GUI singleton = null;
	private static final int DEFAULT_GUI_PORT = 8080;
	
	/** Main Debugger Panel**/
	private HyPeerWebDebugger debugger;
	
	private HyPeerWeb hypeerweb = null;
	private JScrollPane scrollPane;
	private GUIObserver observer = null;
	
	/**
	 * Creates and initializes the GUI as being the root
	 */
	public GUI(HyPeerWeb hypeerweb){
		observer = new GUIObserver(this);
		this.hypeerweb = hypeerweb;
		this.hypeerweb.addListener(observer);
		
		this.setTitle("HyPeerWeb DEBUGGER V 1.1");

		this.addWindowListener(new WindowAdapter() {
			@Override
			  public void windowClosing(WindowEvent we) {
				shutdown();
			    System.exit(0);
			  }
			});
		
		debugger = new HyPeerWebDebugger(this);
		scrollPane = new JScrollPane(debugger);
		scrollPane.setPreferredSize(new Dimension(debugger.WIDTH+20, debugger.HEIGHT));
		
		this.getContentPane().add(scrollPane);
		
		this.pack();
		
	}
	
	public void setHyPeerWeb(HyPeerWeb newHypeerweb)
	{
		if (hypeerweb != null)
		{
			hypeerweb.removeListener(observer);
		}
		
		hypeerweb = newHypeerweb;
		
		if (hypeerweb != null)
		{
			hypeerweb.addListener(observer);
			debugger.getMapper().getNodeListing().setListSize(hypeerweb.calculateWebSize());
		}
	}
	
	private void shutdown(){
		if (hypeerweb != null)
		{
			hypeerweb.removeListener(observer);
			setHyPeerWeb(null);
		}
	}
	
	public static GUI getSingleton(HyPeerWeb hypeerweb){
		if(singleton == null){
			try{
				singleton = new GUI(hypeerweb);
						
				singleton.setVisible(true);
			}
			catch(Exception e)	{
				JOptionPane.showMessageDialog(null, e.getMessage(), "ERROR",JOptionPane.ERROR_MESSAGE);
				e.printStackTrace();
				System.exit(1);
			}
		}
		return singleton;
	}
	
	private static String getCommandLineArgument(String targetArg, String[] args)
	{
		targetArg = "-" + targetArg;
		
		for (int i = 0; i < args.length; ++i) {
			boolean portParam = args[i].equals(targetArg);
			boolean hasAnotherParam = (i + 1) < args.length;
			if (portParam && hasAnotherParam)
			{
				return args[i+1];
			}
		}
		
		return null;
	}
	
	private static String getSegmentIP(String[] args)
	{
		String result = getCommandLineArgument("sip", args);
		
		if (result != null)
			return result;
		
		try
		{
			return InetAddress.getLocalHost().getHostAddress();
		}
		catch (UnknownHostException e)
		{
			System.err.println("Could not resovle local ip address");
			return null;
		}
	}

	private static PortNumber getSegmentPort(String[] args)
	{	
		String result = getCommandLineArgument("sp", args);

		if (result != null)
		{
			try
			{
				return new PortNumber(Integer.parseInt(result));
			}
			catch (NumberFormatException e)
			{
				
			}
		}
		
		return PortNumber.DEFAULT_PORT_NUMBER;
	}

	private static PortNumber getPort(String[] args)
	{	
		String result = getCommandLineArgument("p", args);

		if (result != null)
		{
			try
			{
				return new PortNumber(Integer.parseInt(result));
			}
			catch (NumberFormatException e)
			{
				
			}
		}
		
		return new PortNumber(GUI.DEFAULT_GUI_PORT);
	}
	
	/**
	 * Start Point of the Program
	 */
	public static void main (String[] args){
		try{
			PortNumber port = getPort(args);
			System.out.println("Starting hypeerweb gui on port " + port);
			System.out.println("==========================================================================================================");
			PeerCommunicator.createPeerCommunicator(port);
		}catch(Exception e){
			System.err.println(e.getMessage());
			System.err.println(e.getStackTrace());
		}

		String targetIP = getSegmentIP(args);
		PortNumber targetPort = getSegmentPort(args);
		HyPeerWebProxy proxy = new HyPeerWebProxy(new GlobalObjectId(targetIP, targetPort, new LocalObjectId(HyPeerWeb.HYPEER_WEB_LOCAL_ID)));
		
		getSingleton(proxy);
	};

	/**
	 * Retrieves the HyPeerWeb Debugging Panel
	 * @return HyPeerWebDebugger
	 */
	public HyPeerWebDebugger getHyPeerWebDebugger() {
		return debugger;
	}
	
	public HyPeerWeb getHyPeerWeb(){
		return hypeerweb;
	}
	
	public void disconnectFromWeb() {
		hypeerweb = null;
	}
	
	public void printToTracePanel(Object msg){
		debugger.getTracePanel().print(msg);
	}
	
	/**
	 *
	 */
	@Override
	public void finalize(){
		
	}

}
